home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 24
/
Amiga Format AFCD24 (Feb 1998, Issue 108).iso
/
-seriously_amiga-
/
shareware
/
programming
/
c
/
amivogl-mdev
/
src
/
amiga.c.bak
< prev
next >
Wrap
Text File
|
1998-01-12
|
38KB
|
1,314 lines
/*
* Vogle driver for the Amiga
*
* Written By: Dr. Charles E. Campbell, Jr.
* Version : 1.00
* Date : September 28, 1993
*
*/
#include <stdio.h>
// #include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include <functions.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <graphics/rastport.h>
#include <graphics/gfxmacros.h>
#include <graphics/text.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/console_protos.h>
#include "vogl.h"
#define INTUITION_REV ((unsigned long) 33L)
#define GRAPICS_REV ((unsigned long) 33L)
/* --------------------------------------------------------------------------
* Definitions Section:
*/
#define SNGLBUFMODE 0 /* default scrbufmode value */
#define DBLBUFMODE 1 /* scrbufmode value */
#define RAWKEYBUF 128 /* initial size of rawkey buffer conversion */
#define KEYBUF 256 /* max size of keybuffer to be read */
#define FONTSEP ';'
#define MAXVRTX 200
#define MAXSTRING 1024
#ifdef SASC
#define USESVMODE
#endif
#ifdef AZTEC_C
#define MEMTYPE (MEMF_ANY|MEMF_CLEAR)
#else
#define MEMTYPE (MEMF_ANY|MEMF_CLEAR)
#endif
/* head_link: handles the generation of head-linked lists. Note that
* each structure is assumed to have the member "nxt".
* The new member becomes "head" - ie. oldest is last in the linked list,
* the newest is first.
*/
#define head_link(structure,head,fail_msg) { \
structure *newstr; \
newstr= (structure *) malloc(sizeof(structure)); \
if(!newstr) printf("***out of memory*** <%s>\n",fail_msg); \
newstr->nxt= head; \
head = newstr; \
}
/* stralloc: allocates new memory for and copies a string into the new mem */
#define stralloc(ptr,string,fail_msg) { \
ptr= (char *) calloc((size_t) strlen(string) + 1,sizeof(char)); \
if(!ptr) printf("***out of memory*** <%s>\n",fail_msg); \
strcpy(ptr,string); \
}
/* --------------------------------------------------------------------------
* Typedefs:
*/
typedef struct FontList_str FontList;
/* --------------------------------------------------------------------------
* Data Structures:
*/
struct FontList_str {
char *fontspec;
struct TextFont *textfont;
FontList *nxt;
};
/* --------------------------------------------------------------------------
* Extern Data:
*/
#ifdef AZTEC_C
extern int Enable_Abort;
#else
void __regargs __checkabort (void);
#endif
/* --------------------------------------------------------------------------
* Local Data:
*/
WORD *voglareaBuffer= NULL;
struct BitMap *voglback = NULL;
struct BitMap *voglfront = NULL;
struct DiskFontBase *DiskfontBase = NULL;
struct GfxBase *GfxBase = NULL;
struct IntuiText *voglitext = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct IOStdReq *vogl_cd_ioreq = NULL;
struct Library *ConsoleDevice = NULL;
struct RastPort *voglrastport = NULL;
struct Screen *voglscreen = NULL;
struct TextAttr *vogltextattr = NULL;
struct TmpRas *vogltmpras = NULL;
struct Window *voglwindow = NULL;
static char useborder = 0;
static char scrbufmode = SNGLBUFMODE;
static char *rawkeybuf = NULL;
static int grfxmode = 0;
static int currcolor = 0;
static UBYTE *voglstring = NULL;
static UWORD scrdepth = 4;
static UWORD scrwidth = 0;
static UWORD scrheight = 0;
static UWORD voglscrbordleft = 0;
static UWORD voglscrbordright= 0;
static UWORD voglscrbordtop = 0;
static UWORD voglscrbordbttm = 0;
static USHORT screenviewmode = HIRES|LACE;
static LONG qtyrawkeybuf = 0L;
static FontList *fontlisthd = NULL;
static struct InputEvent *voglievent = NULL;
static PLANEPTR voglplaneptr = NULL;
/* voglkeybuf
* |uuuddddddduuuuu| u=unused d=data
* ^ ^
* ikeybgn ikeyend (always point to unused)
*/
static char voglkeybuf[KEYBUF];
static unsigned ikeyend= 0; /* points just-past chars in voglkeybuf */
static unsigned ikeybgn= KEYBUF-1; /* points just-before chars in voglkeybuf */
/* --------------------------------------------------------------------------
* Local Prototypes:
*/
static int AMIGA_config(char *); /* amiga.c */
static int AMIGA_init(void); /* amiga.c */
static struct BitMap *makeBitMap(void); /* amiga.c */
static int freeBitMap(struct BitMap *); /* amiga.c */
static int AMIGA_exit(void); /* amiga.c */
static int AMIGA_draw( int, int); /* amiga.c */
static int AMIGA_getkey(void); /* amiga.c */
static int AMIGA_checkkey(void); /* amiga.c */
static int AMIGA_locator( int *, int *); /* amiga.c */
static int AMIGA_clear(void); /* amiga.c */
static int AMIGA_color(int); /* amiga.c */
static int AMIGA_mapcolor( int, int, int, int); /* amiga.c */
static int AMIGA_font(char *); /* amiga.c */
static int AMIGA_char(char); /* amiga.c */
static int AMIGA_string(char *); /* amiga.c */
static int AMIGA_fill( int, int[], int[]); /* amiga.c */
static int AMIGA_backbuffer(void); /* amiga.c */
static int AMIGA_swapbuffer(void); /* amiga.c */
static int AMIGA_frontbuffer(void); /* amiga.c */
void _AMIGA_devcpy(void); /* amiga.c */
/* --------------------------------------------------------------------------
* Device Entry
* fontname;height[;{BEIPU}]
* B == bold
* E == extended
* I == italic
* P == plain (default)
* U == underlined
*/
static DevEntry amigadev = {
"AMIGA", /* name of device */
"topaz;9;P", /* name of small "hardware" font */
"topaz;11;P", /* name of large "hardware" font */
AMIGA_backbuffer, /* initializes double buffering */
AMIGA_char, /* prints a "hardware" character */
AMIGA_checkkey, /* check if keyboard key hit, return it */
AMIGA_clear, /* clears viewport to background */
AMIGA_color, /* change current color index */
AMIGA_draw, /* draws line from current to (x,y) */
AMIGA_exit, /* cleans up and allows vogle to exit */
AMIGA_fill, /* does filled polygons */
AMIGA_font, /* sets up a hardware font */
AMIGA_frontbuffer, /* switches drawing into front buffer */
AMIGA_getkey, /* gets a char of input */
AMIGA_init, /* enables graphics */
AMIGA_locator, /* finds mouse position in vogle device coords */
AMIGA_mapcolor, /* changes color at index to given rgb value */
AMIGA_string, /* prints a string of hardware text */
AMIGA_swapbuffer}; /* swaps front and back buffers */
/* ==========================================================================
* Source Code:
*/
/* AMIGA_config: This function modifies what AMIGA_init does. It allows the
* user to control the type of screen and bitmaps used. Note that one may
* use extra half-brite mode, too. I put in ham mode since I expect to
* attempt to do some shading someday.
*
* The AMIGA_init sets up a gimmezerozero window using a custom Screen and
* BitMap.
*
* The config string may include:
* b : use border&title on window
* d : double buffer mode
* e : extra halfbrite mode
* h : ham graphics mode
* s : single buffer mode
* 1-5 : 1,2,3, 4, 5 bit planes (2,4,8,16,64 colors, respectively)
*
* Screen height will be max and interlaced.
* Screen width will be 640 for 1-4 bit planes and 320 otherwise
*/
static int AMIGA_config(char *config)
{
// Enable_Abort=0;
for(; *config; ++config) switch(*config) {
case 'b': /* use border on window */
useborder= 1;
break;
case 'd': /* double buffer mode */
scrbufmode= DBLBUFMODE;
break;
case 'e': /* extra halfbrite mode */
screenviewmode= LACE|EXTRA_HALFBRITE;
scrdepth = 6;
break;
case 'h': /* ham mode */
screenviewmode= LACE|HAM;
scrdepth = 6;
break;
case 's': /* single buffer mode */
scrbufmode= SNGLBUFMODE;
break;
case '1': /* one bit plane */
screenviewmode= LACE|HIRES;
scrdepth = 1;
break;
case '2': /* two bit planes */
screenviewmode= LACE|HIRES;
scrdepth = 2;
break;
case '3': /* three bit planes */
screenviewmode= LACE|HIRES;
scrdepth = 3;
break;
case '4': /* four bit planes */
screenviewmode= LACE|HIRES;
scrdepth = 4;
break;
case '5':
screenviewmode= LACE;
scrdepth = 5;
break;
default:
screenviewmode= LACE|HIRES;
scrdepth = 4;
printf("***warning*** AMIGA_config: bad config<%s> string\n",config);
break;
}
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_init: initialises drawing canvas to occupy current window
* a routine which enables graphics on the device, sets the default
* colour map, and sets vdevice.maxS{x,y} and vdevice.minS{x,y} to the
* window size in pixels.
*/
static int AMIGA_init(void)
{
int gx,gy; /* getprefposandsize x,y */
int gxs,gys; /* getprefposandsize xs,ys */
struct Screen *wbscreen=NULL;
struct NewScreen *newscreen=NULL;
struct NewWindow *newwindow=NULL;
// Enable_Abort=0;
/* don't let user initialize twice (or more!) */
if(IntuitionBase) {
printf("***warning*** AMIGA_init: attempt to initialize twice!\n");
return 0;
}
/* allocate some memory needed for the ConsoleDevice */
vogl_cd_ioreq= (struct IOStdReq *)
AllocMem(sizeof(struct IOStdReq),MEMTYPE);
if(!vogl_cd_ioreq) {
AMIGA_exit();
printf("***warning*** unable to allocate a IOStdReq\n");
goto initproblem;
}
/* open Intuition */
IntuitionBase= (struct IntuitionBase *)
OpenLibrary((UBYTE *) "intuition.library",INTUITION_REV);
if(IntuitionBase == NULL) {
AMIGA_exit();
printf("***warning*** unable to open Intuition Library\n");
goto initproblem;
}
/* open Graphics */
GfxBase= (struct GfxBase *)
OpenLibrary((UBYTE *) "graphics.library",INTUITION_REV);
if(GfxBase == NULL) {
AMIGA_exit();
printf("***warning*** unable to open Graphics Library\n");
goto initproblem;
}
/* open DiskFont */
DiskfontBase= (struct DiskFontBase *)
OpenLibrary((UBYTE *) "diskfont.library",0L);
if(DiskfontBase == NULL) {
AMIGA_exit();
printf("***warning*** unable to open DiskFont library\n");
goto initproblem;
}
/* open ConsoleDevice */
if(OpenDevice((UBYTE *) "console.device",-1L,(struct IORequest *) vogl_cd_ioreq,0L) != 0) {
AMIGA_exit();
printf("***warning*** unable to open DiskFont library\n");
goto initproblem;
}
ConsoleDevice= (struct Library *) vogl_cd_ioreq->io_Device;
/* determine screen width and height from screenviewmode */
#ifdef USESVMODE
/* this code uses screenviewmode by itself, setting up standard
* height and width
*/
scrwidth= 640;
if( (screenviewmode & HAM) ||
!(screenviewmode & HIRES) ||
(screenviewmode & EXTRA_HALFBRITE)) scrwidth= 320;
scrheight= 256;
if(screenviewmode & LACE) scrheight= 400;
#else
/* lock WorkBench screen and query it for its dimensions */
wbscreen= LockPubScreen((UBYTE *) "Workbench");
if(wbscreen) {
scrheight= wbscreen->Height;
scrwidth = wbscreen->Width;
if ( (wbscreen->ViewPort.Modes & LACE) && !(screenviewmode & LACE)) scrheight/= 2;
else if(!(wbscreen->ViewPort.Modes & LACE) && (screenviewmode & LACE)) scrheight*= 2;
if ( (wbscreen->ViewPort.Modes & HIRES) && !(screenviewmode & HIRES)) scrwidth /= 2;
else if(!(wbscreen->ViewPort.Modes & HIRES) && (screenviewmode & HIRES)) scrwidth *= 2;
voglscrbordtop = wbscreen->WBorTop + wbscreen->Font->ta_YSize + 1;
UnlockPubScreen(NULL,wbscreen);
}
else voglscrbordtop= 0;
#endif
/* allocate a NewScreen in CHIP memory */
newscreen= AllocMem(sizeof(struct NewScreen),MEMTYPE);
if(!newscreen) {
AMIGA_exit();
printf("***warning*** unable to allocate a NewScreen\n");
goto initproblem;
}
/* set up both front and back BitMaps. Note that Vogl signals
* use of double buffering after this function is called
* (the doublebuffer() function calls AMIGA_backbuffer
* which begins backbuffering)
*/
voglfront= makeBitMap();
if(!voglfront) {
AMIGA_exit();
printf("***warning*** unable to allocate front BitMap\n");
goto initproblem;
}
voglback= makeBitMap();
if(!voglback) {
AMIGA_exit();
printf("***warning*** unable to allocate back BitMap\n");
goto initproblem;
}
/* initialize NewScreen */
newscreen->LeftEdge = 0;
newscreen->TopEdge = 0;
newscreen->Width = scrwidth;
newscreen->Height = scrheight;
newscreen->Depth = scrdepth;
newscreen->DetailPen = 1;
newscreen->BlockPen = 0;
newscreen->ViewModes = windowviewmode;
newscreen->Type = CUSTOMSCREEN|CUSTOMBITMAP|SCREENQUIET;
newscreen->Font = (struct TextAttr *) NULL;
newscreen->DefaultTitle= (UBYTE *) NULL;
newscreen->CustomBitMap= voglfront;
voglscreen = wbscreen;
/*
voglscreen = OpenScreen(newscreen);
FreeMem(newscreen,sizeof(struct NewScreen));
*/
if(!voglscreen) {
AMIGA_exit();
printf("***warning*** unable to open a Screen\n");
goto initproblem;
}
/* allocate and initialize a window */
newwindow= AllocMem((LONG) sizeof(struct NewWindow),MEMTYPE);
if(!newwindow) {
AMIGA_exit();
printf("***warning*** unable to allocate a NewWindow\n");
goto initproblem;
}
/* get user-specified initial window position and size
* The user specifies these parameters with
*
* prefposition(long x,long y)
* prefsize(long xs,long ys)
*
* *prior* to calling winopen() or ginit().
* Vogl initializes gx, gy, gxs, gys to -1
*/
getprefposandsize(&gx,&gy,&gxs,&gys);
if(gx < 0 || scrwidth < gx) gx = 0;
if(gy < 0 || scrheight < gy) gy = 0;
if(gxs < 0 || scrwidth < gxs) gxs= scrwidth;
if(gys < 0 || scrheight < gys) gys= scrheight;
/* the amiga driver's standard window */
newwindow->LeftEdge = (SHORT) gx;
newwindow->TopEdge = (SHORT) gy;
newwindow->Width = (SHORT) gxs;
newwindow->Height = (SHORT) gys;
newwindow->DetailPen = (UBYTE) -1;
newwindow->BlockPen = (UBYTE) -1;
newwindow->IDCMPFlags = (ULONG) IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
newwindow->Flags = REPORTMOUSE | ACTIVATE | RMBTRAP;
newwindow->FirstGadget= (struct Gadget *) NULL;
newwindow->CheckMark = (struct Image *) NULL;
newwindow->Title = (UBYTE *) NULL;
newwindow->Screen = voglscreen;
newwindow->BitMap = voglfront;
newwindow->MinWidth = 0;
newwindow->MinHeight = 0;
newwindow->MaxHeight = ~0;
newwindow->MaxWidth = ~0;
newwindow->Type = CUSTOMSCREEN;
/* configuration modifications */
if(!useborder) newwindow->Flags|= BORDERLESS;
else {
int Yfont;
if(vdevice.wintitle && vdevice.wintitle[0]) {
newwindow->Title= (UBYTE *) vdevice.wintitle;
}
Yfont = voglscreen->Font? voglscreen->Font->ta_YSize : 0;
voglscrbordtop = voglscreen->WBorTop + Yfont + 1;
voglscrbordbttm = voglscreen->WBorBottom;
voglscrbordleft = voglscreen->WBorLeft;
voglscrbordright = voglscreen->WBorRight;
}
/* open the window */
voglwindow= OpenWindow(newwindow);
FreeMem(newwindow,sizeof(struct NewWindow));
if(!voglwindow) {
AMIGA_exit();
printf("***warning*** unable to allocate a NewWindow\n");
goto initproblem;
}
/* set voglrastport up */
voglrastport = &voglscreen->RastPort;
voglscreen->RastPort.BitMap= voglscreen->ViewPort.RasInfo->BitMap=
(scrbufmode == DBLBUFMODE)? voglback : voglfront;
/* initialize areaBuffer (5 bytes, not words, per vertex) */
voglareaBuffer= (WORD *) AllocMem((LONG) 5*MAXVRTX,MEMTYPE);
if(!voglareaBuffer) {
AMIGA_exit();
printf("***warning*** unable to initialize areaBuffer for %d vertices\n",MAXVRTX);
goto initproblem;
}
voglrastport->AreaInfo= (struct AreaInfo *)
AllocMem((LONG) sizeof(struct AreaInfo),MEMTYPE);
if(!voglrastport->AreaInfo) {
AMIGA_exit();
printf("***warning*** unable to initialize areaInfo\n");
goto initproblem;
}
InitArea(voglrastport->AreaInfo,voglareaBuffer,MAXVRTX);
/* initialize a TmpRas */
vogltmpras= (struct TmpRas *)
AllocMem((LONG) sizeof(struct TmpRas),MEMTYPE);
if(!vogltmpras) {
AMIGA_exit();
printf("***warning*** unable to allocate a TmpRas\n");
goto initproblem;
}
voglplaneptr= (PLANEPTR) AllocRaster(scrwidth,scrheight);
if(voglplaneptr) {
voglrastport->TmpRas= (struct TmpRas *)
InitTmpRas(vogltmpras,voglplaneptr,RASSIZE(scrwidth,scrheight));
}
else {
AMIGA_exit();
printf("***warning*** unable to allocate a %dx%d raster for TmpRas\n",
scrwidth,scrheight);
goto initproblem;
}
/* don't outline area fills with the OPen (outline color pen) */
BNDRYOFF(voglrastport);
/* set up strings and fonts */
voglitext = (struct IntuiText *) AllocMem((LONG) sizeof(struct IntuiText),MEMTYPE);
voglstring = (UBYTE *) AllocMem((LONG) MAXSTRING*sizeof(UBYTE),MEMTYPE);
vogltextattr= (struct TextAttr *) AllocMem((LONG) sizeof(struct TextAttr),MEMTYPE);
/* optionally set up double buffering via AMIGA_backbuffer() */
if(scrbufmode == DBLBUFMODE) AMIGA_backbuffer();
/* initial rawkey buffer allocation */
if(!rawkeybuf) {
qtyrawkeybuf= RAWKEYBUF;
rawkeybuf = (char *) AllocMem(qtyrawkeybuf,MEMTYPE);
if(!rawkeybuf) { /* terminate on no buffer */
AMIGA_exit();
printf("***warning*** unable to allocate a %ld byte buffer for rawkeys\n",
qtyrawkeybuf);
goto initproblem;
}
}
/* allocate an InputEvent */
voglievent= (struct InputEvent *) AllocMem(sizeof(struct InputEvent),MEMTYPE);
if(!voglievent) {
AMIGA_exit();
printf("***warning*** unable to allocate an InputEvent\n");
goto initproblem;
}
/* initialize vogl screensize variables*/
vdevice.sizeSx= scrwidth - 1; /* x: upper right corner */
vdevice.sizeSy= scrheight - 1; /* y: upper right corner */
vdevice.depth = scrdepth; /* z: qty bitplanes */
vdevice.sizeX = vdevice.sizeY= (scrheight < scrwidth)? scrheight : scrwidth;
/* initialize the colormap */
AMIGA_mapcolor(0, 0, 0, 0); /* black */
AMIGA_mapcolor(1,15, 0, 0); /* red */
if(scrdepth >= 2) {
AMIGA_mapcolor(2, 0,15, 0); /* green */
AMIGA_mapcolor(3,15,15, 0); /* yellow */
if(scrdepth >= 3) {
int icolor;
AMIGA_mapcolor(4, 0, 0,15); /* blue */
AMIGA_mapcolor(5,15, 0,15); /* magenta */
AMIGA_mapcolor(6, 0,15,15); /* cyan */
AMIGA_mapcolor(7,15,15,15); /* white */
/* make the rest, if any, black */
for(icolor= 8; icolor < (1<<scrdepth); ++icolor)
AMIGA_mapcolor(icolor,0,0,0);
}
}
return 1;
initproblem:
return(0);
}
/* -------------------------------------------------------------------------- */
/* makeBitMap: this function sets up one bitmap. Double buffering, of
* course, requires two bitmaps.
*/
static struct BitMap *makeBitMap(void)
{
int idepth;
struct BitMap *bitmap=NULL;
/* allocate BitMap itself */
bitmap= AllocMem((LONG) sizeof(struct BitMap),MEMTYPE);
if(bitmap) {
InitBitMap(bitmap,(LONG) scrdepth,(LONG) scrwidth,(LONG) scrheight);
for(idepth= 0; idepth < scrdepth; ++idepth) {
bitmap->Planes[idepth]= (PLANEPTR) AllocRaster(scrwidth,scrheight);
if(!bitmap->Planes[idepth]) { /* unable to get enough memory */
for(--idepth; idepth >= 0; --idepth)
FreeRaster(bitmap->Planes[idepth],scrwidth,scrheight);
FreeMem(bitmap,(LONG) sizeof(struct BitMap));
break;
}
BltClear(bitmap->Planes[idepth],(scrwidth>>3)*scrheight,1);
}
}
return bitmap;
}
/* -------------------------------------------------------------------------- */
/* freeBitMap: this function frees up memory used by a BitMap */
static int freeBitMap(struct BitMap *bitmap)
{
int idepth;
for(idepth= scrdepth-1; idepth >= 0; --idepth) {
FreeRaster(bitmap->Planes[idepth],scrwidth,scrheight);
}
FreeMem(bitmap,(LONG) sizeof(struct BitMap));
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_exit: cleans up before returning the window to normal
* Note: I've designed this driver so that it can be re-opened.
*/
static int AMIGA_exit(void)
{
FontList *prvfontlist;
/* clear back screen */
if(voglscreen) SetRast(&(voglscreen->RastPort),(unsigned long) 0);
/* close open Fonts and clean up memory use */
while(fontlisthd) {
CloseFont(fontlisthd->textfont);
free((char *) fontlisthd->fontspec);
fontlisthd->textfont= NULL;
fontlisthd->fontspec= NULL;
prvfontlist = fontlisthd;
fontlisthd = fontlisthd->nxt;
free((char *) prvfontlist);
}
fontlisthd= NULL;
/* free up rawkey buffer */
if(voglievent) FreeMem(voglievent,sizeof(struct InputEvent));
if(rawkeybuf) FreeMem(rawkeybuf,qtyrawkeybuf);
if(vogltextattr->ta_Name) {
int slen;
slen= strlen((char *) vogltextattr->ta_Name);
if(slen & 1) ++slen;
FreeMem(vogltextattr->ta_Name,slen*sizeof(char));
vogltextattr->ta_Name= NULL;
}
if(vogltextattr) FreeMem(vogltextattr,sizeof(struct TextAttr));
if(voglstring) FreeMem(voglstring,MAXSTRING*sizeof(UBYTE));
if(voglitext) FreeMem(voglitext,sizeof(struct IntuiText));
vogltextattr= NULL;
voglstring = NULL;
voglitext = NULL;
if(voglplaneptr) {
FreeRaster(voglplaneptr,scrwidth,scrheight);
voglplaneptr= NULL;
}
if(vogltmpras) {
FreeMem(vogltmpras,sizeof(struct TmpRas));
}
voglrastport->TmpRas= vogltmpras= NULL;
if(voglrastport->AreaInfo) {
FreeMem(voglrastport->AreaInfo,sizeof(struct AreaInfo));
}
voglrastport->AreaInfo= NULL;
if(voglareaBuffer) {
FreeMem(voglareaBuffer,5*MAXVRTX);
}
voglareaBuffer= NULL;
if(voglwindow) {
CloseWindow(voglwindow);
}
voglwindow= NULL;
if(voglscreen) {
CloseScreen(voglscreen);
}
voglscreen= NULL;
/* free up BitMaps */
if(voglback) freeBitMap(voglback);
if(voglfront) freeBitMap(voglfront);
voglfront= voglback= NULL;
/* close down Libraries */
if(ConsoleDevice) {
CloseDevice((struct IORequest *) vogl_cd_ioreq);
}
ConsoleDevice= NULL;
if(DiskfontBase) {
CloseLibrary((struct Library *) DiskfontBase);
}
DiskfontBase= NULL;
if(GfxBase) {
CloseLibrary((struct Library *) GfxBase);
}
GfxBase= NULL;
if(IntuitionBase) {
CloseLibrary((struct Library *) IntuitionBase);
}
IntuitionBase= NULL;
/* free up memory for Console Device */
if(vogl_cd_ioreq) {
FreeMem(vogl_cd_ioreq,sizeof(struct IOStdReq));
}
vogl_cd_ioreq= NULL;
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_draw: draws a line from the current graphics position to (x, y) */
static int AMIGA_draw( int x, int y)
{
Move(voglrastport,vdevice.cpVx,vdevice.sizeSy - vdevice.cpVy);
Draw(voglrastport,x,vdevice.sizeSy - y);
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_getkey: grab a character from the keyboard
* (empties voglkeybuf)
*/
static int AMIGA_getkey(void)
{
int key;
int mb,wx,wy; /* to make AMIGA_locator happy */
int newikeybgn;
ULONG signals;
newikeybgn= ikeybgn + 1;
if(newikeybgn >= KEYBUF) newikeybgn= 0;
if(newikeybgn != ikeyend) {
/* update ikeybgn index and get key from voglkeybuf */
ikeybgn= newikeybgn;
key = voglkeybuf[ikeybgn];
}
else {
/* block until a key is hit */
do {
signals= Wait(1L << voglwindow->UserPort->mp_SigBit);
if(signals & (1L << voglwindow->UserPort->mp_SigBit)) {
mb= AMIGA_locator(&wx,&wy);
}
} while(newikeybgn == ikeyend);
/* update ikeybgn index and get key from voglkeybuf */
ikeybgn= newikeybgn;
key = voglkeybuf[ikeybgn];
}
return key;
}
/* -------------------------------------------------------------------------- */
/* AMIGA_checkkey: Check if a keyboard key has been hit. If so return it
* Otherwise, return 0. Note: this function does actually read the
* key (ie. remove it from the buffer) if one has been hit. That's
* the way the qread/qtest functions like it.
*/
static int AMIGA_checkkey(void)
{
int key;
int mb,wx,wy; /* to make AMIGA_locator happy */
int newikeybgn;
/* fill up rawkeybuf with any pending key hits */
mb = AMIGA_locator(&wx,&wy);
newikeybgn= ikeybgn + 1;
if(newikeybgn >= KEYBUF) newikeybgn= 0;
if(newikeybgn != ikeyend) {
ikeybgn= newikeybgn;
key = voglkeybuf[ikeybgn];
}
else key= 0;
return key;
}
/* -------------------------------------------------------------------------- */
/* AMIGA_handlekey: this function handles RAWKEYs (fills up voglkeybuf)
* voglkeybuf voglkeybuf
* |uuuddddddduuuuu| u=unused d=data |ddddduuuuuuudd|
* ^ ^ ^ ^
* ikeybgn ikeyend (always point to unused) ikeyend ikeybgn
*/
static void AMIGA_handlekey(struct IntuiMessage *Imsg)
{
int dbl=0;
LONG numchars;
unsigned newikeyend;
/* convert rawkey message into a vanilla key */
do {
voglievent->ie_Class = IECLASS_RAWKEY;
voglievent->ie_Code = Imsg->Code;
voglievent->ie_Qualifier = Imsg->Qualifier;
voglievent->ie_position.ie_addr= *((APTR*) Imsg->IAddress);
numchars= RawKeyConvert(voglievent,(STRPTR) rawkeybuf,qtyrawkeybuf-1,NULL);
dbl = numchars == -1 && !rawkeybuf[0];
if(dbl) { /* double size of rawkeybuf to enable conversion */
FreeMem(rawkeybuf,qtyrawkeybuf);
qtyrawkeybuf<<= 1;
rawkeybuf = AllocMem(qtyrawkeybuf,MEMTYPE);
if(!rawkeybuf) { /* unable to double rawkey buffer! */
qtyrawkeybuf= 0;
AMIGA_exit();
}
}
} while(dbl);
/* numchars contains the number of characters placed within the rawkeybuf.
* Key up events and key sequences which do not generate any data for the
* program (deadkeys, already intercepted sequences, etc) will return zero.
*
* Special keys (HELP, cursor keys, FKeys, etc) return multiple characters
* that have to be parsed below.
*
* There are a number of qualifiers available, most of which are currently
* being ignored by this vogl-amiga driver. However, for reference purposes:
*
* (Imsg->Code & 0x80)? key-up : key-down
*
* Imsg->Qualifier can be "anded" with
*
* IEQUALIFIER_CAPSLOCK IEQUALIFIER_LSHIFT IEQUALIFIER_RBUTTON
* IEQUALIFIER_CONTROL IEQUALIFIER_MIDBUTTON IEQUALIFIER_RCOMMAND
* IEQUALIFIER_INTERRUPT IEQUALIFIER_MULTIBROADCAST IEQUALIFIER_RELATIVEMOUSE
* IEQUALIFIER_LALT IEQUALIFIER_NUMERICPAD IEQUALIFIER_REPEAT
* IEQUALIFIER_LCOMMAND IEQUALIFIER_RALT IEQUALIFIER_RSHIFT
* IEQUALIFIER_LEFTBUTTON
*/
/* key is pressed down */
if(!(Imsg->Code & 0x80)) {
/* handlekey only accepts alphameric (assumed to be caps), numeric, and unshifted
* punctuation. Report sequences (function keys, help, cursor keys, etc) are
* ignored!
*/
newikeyend= ikeyend + 1;
if(newikeyend >= KEYBUF) newikeyend= 0;
if(newikeyend != ikeybgn && rawkeybuf[0] != 0x9b) { /* 0x9b is a report sequence */
if (islower(rawkeybuf[0])) rawkeybuf[0]= toupper(rawkeybuf[0]); /* lower -> upper */
else if(rawkeybuf[0] == '\177') rawkeybuf[0]= '\020'; /* DEL key mapping */
voglkeybuf[ikeyend]= rawkeybuf[0];
ikeyend = newikeyend;
}
}
}
/* --------------------------------------------------------------------- */
/* AMIGA_locator:
* return the window location of the cursor,
* plus which mouse button, if any, has been pressed.
*
* Bit 0 1 2 is 1 when button is pressed down
* |left|middle|right| is 0 when button is released
*/
static int AMIGA_locator( int *wx, int *wy)
{
int mb = 0;
struct Message *Mmsg= NULL;
struct IntuiMessage *Imsg= NULL;
/* get current mouse position */
*wx= voglwindow->MouseX;
*wy= vdevice.sizeSy - voglwindow->MouseY;
while(Mmsg= GetMsg(voglwindow->UserPort)) {
Imsg= (struct IntuiMessage *) Mmsg;
switch(Imsg->Class) {
case IDCMP_MOUSEBUTTONS:
switch(Imsg->Code) {
case SELECTDOWN: /* left mouse pressed */
mb|= 01;
break;
case SELECTUP: /* left mouse released */
mb&= ~01;
break;
case MIDDLEDOWN: /* middle mouse pressed */
mb|= 02;
break;
case MIDDLEUP: /* middle mouse released */
mb&= ~02;
break;
case MENUDOWN: /* right mouse pressed */
mb|= 04;
break;
case MENUUP: /* right mouse released */
mb&= ~04;
break;
default:
break;
}
break;
case IDCMP_RAWKEY: /* a key was hit/released */
AMIGA_handlekey(Imsg);
break;
default: /* unsupported Intuimessage */
break;
}
ReplyMsg(Mmsg);
}
return mb;
}
/* -------------------------------------------------------------------------- */
/* AMIGA_clear: Clear the screen to current color */
static int AMIGA_clear(void)
{
SetRast(voglrastport,(unsigned long) currcolor);
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_color: set the current drawing color index */
static int AMIGA_color(int icolor)
{
currcolor= icolor; /* used by string/char rendering */
SetAPen(voglrastport,icolor);
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_mapcolor: change index icolor in the color map to the appropriate
* r, g, b, value.
*/
static int AMIGA_mapcolor( int icolor, int r, int g, int b)
{
if(icolor >= (1<<scrdepth)) {
return(0);
}
SetRGB4(&voglscreen->ViewPort,
(long) icolor,
(unsigned long) r,
(unsigned long) g,
(unsigned long) b);
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_font: Set up a hardware font. Return 1 on success 0 otherwise
* I have come up with a little convention for the fontspec:
* fontname;height[;{BEIPU}]
* B == bold
* E == extended
* I == italic
* P == plain (default)
* U == underlined
*
* Returns: 0=failure-to-open
* 1=successful font open
*/
static int AMIGA_font(char *fontspec)
{
char type='P'; /* font spec type */
char *fsh; /* ptr to font spec height */
char *fst; /* ptr to font spec type */
// int h; /* height */
int slen; /* length of fontname */
FontList *fontlist = NULL;
struct TextFont *vogltextfont= NULL;
static FontList *oldfontlist = NULL;
/* check over FontList for fontspec */
for(fontlist= fontlisthd; fontlist; fontlist= fontlist->nxt) {
if(!strcmp(fontlist->fontspec,fontspec)) {
if(fontlist == oldfontlist) { /* font unchanged! */
return(0);
}
vdevice.hheight= fontlist->textfont->tf_YSize;
vdevice.hwidth = fontlist->textfont->tf_XSize;
/* set the font */
SetFont(voglrastport,fontlist->textfont);
oldfontlist= fontlist;
return 1;
}
}
/* get font-separator pointers */
fsh = strchr(fontspec,FONTSEP); /* nominal font height */
fst = strchr(fsh+1,FONTSEP); /* type of font */
vogltextattr->ta_Style= (UBYTE) 0; /* default style == plain */
vogltextattr->ta_Flags= (UBYTE) 0; /* default style == plain */
if(fsh) {
sscanf(fsh+1,"%hu",&vogltextattr->ta_YSize);
*fsh= '\0';
if(fst) {
for(++fst; *fst; ++fst) switch(*fst) {
case 'B': /* bold */
case 'b':
vogltextattr->ta_Style|= FSF_BOLD;
break;
case 'E': /* extended (extra wide) */
case 'e':
vogltextattr->ta_Style|= FSF_EXTENDED;
break;
case 'I': /* italic */
case 'i':
vogltextattr->ta_Style|= FSF_ITALIC;
break;
case 'P': /* plain */
case 'p':
break;
case 'U': /* underlined */
case 'u':
vogltextattr->ta_Style|= FSF_UNDERLINED;
break;
default: /* ignored */
break;
}
}
}
else vogltextattr->ta_YSize= 11L; /* default height == 11 pts */
/* free up old ta_Name */
if(vogltextattr->ta_Name) {
slen= strlen((char *) vogltextattr->ta_Name);
if(slen & 1) ++slen;
FreeMem(vogltextattr->ta_Name,slen*sizeof(char));
vogltextattr->ta_Name= NULL;
}
slen= strlen(fontspec) + 6;
if(slen & 1) ++slen;
vogltextattr->ta_Name= (STRPTR) AllocMem((LONG) slen*sizeof(char),MEMTYPE);
sprintf((char *) vogltextattr->ta_Name,"%s.font",fontspec);
if(fsh) *fsh= FONTSEP; /* restore *fsh */
/* attempt to open requested font */
vogltextfont= OpenDiskFont(vogltextattr); /* open the font */
if(vogltextfont) {
SetFont(voglrastport,vogltextfont); /* set the font */
/* set up FontList */
head_link(FontList,fontlisthd,"FontList");
stralloc(fontlisthd->fontspec,fontspec,"fontspec");
fontlisthd->textfont= vogltextfont;
oldfontlist = fontlisthd;
vdevice.hheight = fontlisthd->textfont->tf_YSize;
vdevice.hwidth = fontlisthd->textfont->tf_XSize;
}
else { /* failure to open requested font */
vdevice.hheight= 0;
vdevice.hwidth = 0;
return 0;
}
return 1;
}
/* -------------------------------------------------------------------------- */
/* AMIGA_char: outputs one char */
static int AMIGA_char(char c)
{
char s[2];
s[0]= c;
s[1]= '\0';
AMIGA_string(s);
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_string: Display a string at the current drawing position */
static int AMIGA_string(char *s)
{
/* set up the IntuiText */
voglitext->FrontPen = (UBYTE) currcolor; /* set text's foreground color */
voglitext->BackPen = (UBYTE) 0; /* background color ignored */
voglitext->DrawMode = JAM1; /* just use fgd color */
voglitext->LeftEdge = vdevice.cpVx; /* set x position */
/* set y position */
voglitext->TopEdge = (short)(vdevice.sizeSy - vdevice.cpVy - vdevice.hheight);
voglitext->ITextFont= NULL; /* use default font */
strcpy((char *) voglstring,s); /* copy user's string to voglstring */
voglitext->IText = voglstring; /* print out voglstring */
voglitext->NextText = NULL; /* no next text */
PrintIText(voglrastport,voglitext,0L,0L); /* use printIText to render */
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_fill: fill a polygon */
static int AMIGA_fill( int n, int *x, int *y)
{
int ifill;
// int result;
if(AreaMove(voglrastport,(long) x[0],(long) vdevice.sizeSy - y[0]) < 0) {
printf("***warning*** unable to fill polygon with %d vertices\n",n);
return(0);
}
for(ifill= 1; ifill < n; ++ifill) {
if(AreaDraw(voglrastport,(long) x[ifill],(long) vdevice.sizeSy - y[ifill]) < 0) {
printf("***warning*** unable to fill polygon with %d vertices\n",n);
return(0);
}
}
AreaEnd(voglrastport);
vdevice.cpVx = x[n - 1];
vdevice.cpVy = y[n - 1];
return(0);
}
/* -------------------------------------------------------------------------- */
/* AMIGA_backbuffer: draw in back buffer, display front
* Returns 0=success
* -1=failure
*/
static int AMIGA_backbuffer(void)
{
if(scrbufmode == SNGLBUFMODE) { /* begin double buffer mode */
scrbufmode = DBLBUFMODE;
voglscreen->RastPort.BitMap= voglscreen->ViewPort.RasInfo->BitMap= voglback;
voglscreen->RastPort.Flags = DBUFFER;
}
if(voglback && voglscreen->RastPort.BitMap != voglback) {
MakeScreen(voglscreen); /* make screen's new copper list */
RethinkDisplay(); /* combine copper lists into single View */
voglscreen->RastPort.BitMap= voglscreen->ViewPort.RasInfo->BitMap= voglback;
voglwindow->RPort->BitMap = voglback;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* AMIGA_swapbuffer: swap the front and back buffers */
static int AMIGA_swapbuffer(void)
{
struct BitMap *voglswap;
if(!voglback || scrbufmode != DBLBUFMODE) {
return 0;
}
/* display back buffer */
MakeScreen(voglscreen); /* make screen's new copper list */
RethinkDisplay(); /* combine copper lists into single View */
/* swap front and back BitMap buffers */
voglswap = voglfront;
voglfront = voglback;
voglback = voglswap;
voglscreen->RastPort.BitMap= voglscreen->ViewPort.RasInfo->BitMap= voglback;
voglwindow->RPort->BitMap = voglback;
return 0;
}
/* -------------------------------------------------------------------------- */
/* AMIGA_frontbuffer: draw in the front buffer */
static int AMIGA_frontbuffer(void)
{
voglscreen->RastPort.BitMap= voglscreen->ViewPort.RasInfo->BitMap= voglfront;
voglwindow->RPort->BitMap = voglfront;
return(0);
}
/* --------------------------------------------------------------------------
* _AMIGA_devcpy
*
* copy the amiga device into vdevice.dev.
*/
void _AMIGA_devcpy(void)
{
vdevice.dev= amigadev;
}
/* ==========================================================================
* Source Code:
* The test code here exercises the amiga driver by itself and is not
* expected to be the "usual" way of using it. The usual way is via
* standard vogl methods.
*/
/* --------------------------------------------------------------------- */
/* DT_title: this function sets up the window's title */
void DT_title(char *buf)
{
static char titlebuf[RAWKEYBUF];
strcpy(titlebuf,buf);
vdevice.wintitle= titlebuf;
}
/* --------------------------------------------------------------------- */
#ifdef SASC
void __regargs __checkabort (void)
{
/* empty */
}
#endif
/* --------------------------------------------------------------------- */